﻿using SuperMap.Data;
using SuperMap.Realspace;
using SuperMap.UI;
using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Windows.Forms;
using Ycjw.PipeLine.Map.Basic.Conditions;
using Ycjw.PipeLine.Map.Basic.SuperMap;
using Ycjw.PipeLine.Map.Tools.Conditions.JJAnalysts;

namespace Ycjw.PipeLine.Map.Tools.Conditions
{
    /// <summary>
    /// 覆土分析
    /// </summary>
    public class FTAnalystToolBar : BasicToolBar
    {
        private readonly double STANDARD_DEEP = 15;

        private int m_Index = -1;
        private TextureForm m_TextureForm;
        public FTAnalystToolBar()
        {
            this.ConditionPanelName = "覆土分析";
            var annlystToolStripButton = new ToolStripButton()
            {
                DisplayStyle = ToolStripItemDisplayStyle.ImageAndText,
                Text = "覆土分析",
                Name = "Analyst"
            };
            base.ToolStrip.Items.Add(annlystToolStripButton);

            annlystToolStripButton.Click += AnnlystToolStripButton_Click;
        }

        private void AnnlystToolStripButton_Click(object sender, System.EventArgs e)
        {
            AddExcavationRegion();
        }

        public void AddExcavationRegion()
        {
            try
            {
                RemoveExcavationRegion();
                SceneControl.Scene.TrackingLayer.Clear();
                SceneControl.Action = Action3D.MeasureArea;
                SceneControl.Tracked -= new Tracked3DEventHandler(SceneControl_Tracked);
                SceneControl.Tracked += new Tracked3DEventHandler(SceneControl_Tracked);
            }
            catch (Exception ex)
            {
                Trace.WriteLine(ex.Message);
            }
        }
        public override void AfterClose()
        {
            UnRegister();
            RemoveExcavationRegion();
            this.Scene.TrackingLayer.Clear();
        }
        private void TextureForm_FormClosed(object sender, FormClosedEventArgs e)
        {
            UnRegister();
        }
        // 清除填挖方区域
        // Remove fill/cut area
        public void RemoveExcavationRegion()
        {
            if (SceneControl.Scene.GlobalImage.ExcavationRegionCount > 0)
            {
                SceneControl.Scene.GlobalImage.ClearExcavationRegions();
            }
        }

        internal void CloseScene()
        {
            SceneControl.Scene.Close();
        }

        public void UnRegister()
        {
            SceneControl.Action = Action3D.Pan;
            SceneControl.Tracked -= new Tracked3DEventHandler(SceneControl_Tracked);
        }
        
        private void Draw(Layer3DDataset lyr3D, DataTable dt)
        {
            if (!(lyr3D.Dataset is DatasetVector)) return;
            DatasetVector dsv = lyr3D.Dataset as DatasetVector;
            var fs = dsv.GetAllFeatures();
            foreach(var f in fs)
            {
                if (!FeatureInDataTable(f.Value, dt)) continue;
                var geoInFeature = f.Value.GetGeometry() as GeoLine3D;
                var point1 = GetFeatureHighestPoint(geoInFeature);
                var zInpoint2 = GetLineDeep(f.Value);
                if (zInpoint2 < 0) continue;
                var point2 = new Point3D(point1.X,point1.Y, zInpoint2 + point1.Z);
                var line3d = new GeoLine3D(new Point3Ds(new Point3D[] { point1, point2 }))
                {
                    Style3D = new GeoStyle3D()
                    {
                        AltitudeMode = AltitudeMode.Absolute,
                        LineColor = Color.Yellow,
                        LineWidth = 4
                    }
                };
                Scene.TrackingLayer.Add(line3d, string.Empty);
                var text = "埋深：" + zInpoint2 + "(米) ";
                text += "标准深度：" + STANDARD_DEEP;
                var textLocation = point2;
                GeoText3D geoText = new GeoText3D(new TextPart3D(text.ToString(), textLocation));
                Styles.SetResultTextStyle(geoText);
                Scene.TrackingLayer.Add(geoText, "埋深");

            }
            Point3D GetFeatureHighestPoint(GeoLine3D line)
            {
                var val = new Point3D(0,0,double.MinValue);
                
                for(var i = 0;i < line.PartCount;i++)
                {
                    var subLine = line[i];
                    for(var j = 0;j < subLine.Count; j++)
                    {
                        var point = subLine[j];
                        if (point.Z > val.Z) val = point;
                    }
                }
                return val;
            }
            double GetLineDeep(Feature feat)
            {
                try
                {
                    var deep1 = feat.GetDouble("起点埋深");
                    var deep2 = feat.GetDouble("终点埋深");
                    return deep1 > deep2 ? deep2 : deep1;
                }
                catch(Exception ex)
                {
                    Commons.LogHelper.Warn("获取‘起点埋深、终点埋深失败’："+ex.Message);
                }
                try
                {
                    var deep = feat.GetDouble("埋深");
                    return deep;
                }
                catch (Exception ex)
                {
                    Commons.LogHelper.Warn("获取‘埋深失败’：" + ex.Message);
                }
                return -1;
            }
            bool FeatureInDataTable(Feature feat,DataTable dataTable)
            {
                foreach(DataRow dr in dataTable.Rows)
                {
                    if(dr["SmID"].ToString() == feat.GetString("Smid"))
                    {
                        return true;
                    }
                }
                return false;
            }
        }
        // 绘制结束时将所绘制的区域添加到挖方区域中
        // Add the drawn region to the cutting area after it is drawn
        private void SceneControl_Tracked(object sender, Tracked3DEventArgs e)
        {
            Scene.TrackingLayer.Clear();
            try
            {
                m_Index++;
                int index = SceneControl.Scene.TrackingLayer.IndexOf("area");
                if (index != -1)
                {
                    SceneControl.Scene.TrackingLayer.Remove(index);
                }

                if (!(e.Geometry is GeoRegion3D geoRegion3D)) return;
                m_TextureForm = new TextureForm
                {
                    Location = Cursor.Position
                };
                m_TextureForm.ShowDialog();
                m_TextureForm.FormClosed += TextureForm_FormClosed;

                if (m_TextureForm.GeoStyle3D != null)
                {
                    geoRegion3D.Style3D = m_TextureForm.GeoStyle3D;
                    SceneControl.Scene.GlobalImage.AddExcavationRegion(geoRegion3D, "ExcavationRegion" + m_Index);
                    /*
                    Camera camera = new Camera
                    {
                        Longitude = geoRegion3D.InnerPoint3D.X,
                        Latitude = geoRegion3D.InnerPoint3D.Y,
                        AltitudeMode = AltitudeMode.Absolute,
                        Altitude = 200,
                        Tilt = 72.5
                    };
                    SceneControl.Scene.Fly(camera);
                    */
                    List<DataTable> dts = new List<DataTable>();
                    foreach (Layer3D lyr in this.Scene.Layers)
                    {
                        if (!(lyr is Layer3DDataset)) continue;
                        Layer3DDataset lyr3D = lyr as Layer3DDataset;
                        if (!(lyr3D.Dataset is DatasetVector)) continue;
                        DatasetVector dsv = lyr3D.Dataset as DatasetVector;
                        if (dsv.Type != DatasetType.Network3D) continue;
                        //对每个管线图层进行（与geoRegion3D）空间包含分析
                        //属性条件比较埋深和标准埋深，不符合条件的过滤出来
                        DatasetVectorEx dve = new DatasetVectorEx(lyr.Name)
                        {
                            DatasetVector = dsv
                        };
                        string where = string.Empty;
                        if(dsv.FieldInfos.IndexOf("起点埋深") > -1 && dsv.FieldInfos.IndexOf("终点埋深") > -1)
                        {
                            where = "起点埋深 <= " + STANDARD_DEEP + " or 终点埋深 <= " + STANDARD_DEEP;
                        }
                        else if(dsv.FieldInfos.IndexOf("埋深") > -1)
                        {
                            where = "埋深 <= " + STANDARD_DEEP;
                        }
                        else
                        {
                            Commons.LogHelper.Warn(lyr.Name + "图层没有埋深字段，未能计算覆土分析情况");
                            continue;
                        }
                        var dt = dve.Query(where, geoRegion3D.ConvertToRegion());
                        dt.TableName = lyr.Caption;
                        //var dt = dve.Query("1=1", geoRegion3D.ConvertToRegion());
                        if (dt!= null && dt.Rows.Count > 0)
                        {
                            Draw(lyr3D, dt);
                            dts.Add(dt);
                        }
                    }
                    this.ShowResult(dts,this.DockPanel,this.ConditionPanelName);

                }
                SceneControl.Action = Action3D.Pan2;

            }
            catch (Exception ex)
            {
                Trace.WriteLine(ex.Message);
            }
        }
    }
}